package top.fyukina.fyson.runtime.loader;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import java.util.HashMap;

public final class ValueLoader {
    public static HashMap<String, Object> vars = new HashMap<>();
    private ValueLoader() {}
    public static Object load(JSONObject obj) {
        if (obj.get("=") instanceof JSONArray v0)
            return compareLoad(v0, "=");
        if (obj.get("!=") instanceof JSONArray v0)
            return compareLoad(v0, "!=");
        if (obj.get("+") instanceof JSONArray v0)
            return mathLoad(v0, "+");
        if (obj.get("*") instanceof JSONArray v0)
            return mathLoad(v0, "*");
        if (obj.get("var") instanceof String v0)
            return varLoad(v0);
        return null;
    }
    public static double mathLoad(JSONArray vals, String r) {
        if (vals == null || vals.size() == 0) return 0D;
        double result = 0D;
        switch (r) {
            case "+" -> {
                for (Object val : vals)
                    if (val instanceof Number val0)
                        result += (val0).doubleValue();
                    else if (val instanceof JSONObject val0) {
                        Object res = load(val0);
                        if (res instanceof Number res0)
                            result += (res0).doubleValue();
                    }
            }
            case "*" -> {
                result = 1D;
                for (Object val : vals)
                    if (val instanceof Number)
                        result *= ((Number) val).doubleValue();
                    else if (val instanceof JSONObject) {
                        Object res = load((JSONObject) val);
                        if (res instanceof Number)
                            result *= ((Number) res).doubleValue();
                    }
            }
        }
        return result;
    }
    public static boolean compareLoad(JSONArray vals, String r) {
        if (vals == null || vals.size() == 0) return true;
        boolean first = true;
        Object flagObj = null;
        switch (r) {
            case "=" -> {
                for (Object val : vals) {
                    if (val == null) return false;
                    /*NULL does not participate in operation.
                     If any, it'll return FALSE directly*/
                    if (val instanceof JSONObject) {
                        Object res = load((JSONObject) val);
                        if (res == null) return false;
                        if (first) {
                            flagObj = res;
                            first = false;
                            continue;
                        }
                        if (res instanceof Number res0) {
                            if (!(flagObj instanceof Number flagObj0)
                                    || !Double.valueOf(res0.doubleValue()).equals((flagObj0).doubleValue()))
                                return false;
                        } else if (res instanceof Boolean res0) {
                            if (!res0.equals(flagObj)) return false;
                        } else if (res instanceof String res0) {
                            if (!res0.equals(flagObj)) return false;
                        } else if (res instanceof Character res0) {
                            if (!res0.equals(flagObj)) return false;
                        } else return false;
                    } else {
                        if (first) {
                            flagObj = val;
                            first = false;
                            continue;
                        }
                        if (val instanceof Number val0) {
                            if (!(flagObj instanceof Number flagObj0)
                                    || !Double.valueOf(val0.doubleValue()).equals((flagObj0).doubleValue()))
                                return false;
                        } else if (val instanceof Boolean val0) {
                            if (!val0.equals(flagObj)) return false;
                        } else if (val instanceof String val0) {
                            if (!val0.equals(flagObj)) return false;
                        } else if (val instanceof Character val0) {
                            if (!val0.equals(flagObj)) return false;
                        } else return false;
                    }
                }
            }
            case "!=" -> {
                for (Object val : vals) {
                    if (val == null) return false;
                    if (val instanceof JSONObject) {
                        Object res = load((JSONObject) val);
                        if (res == null) return false;
                        if (first) {
                            flagObj = res;
                            first = false;
                            continue;
                        }
                        if (res instanceof Number res0) {
                            if (flagObj instanceof Number flagObj0
                                    && Double.valueOf(res0.doubleValue()).equals((flagObj0).doubleValue()))
                                return false;
                        } else if (res instanceof Boolean res0) {
                            if (res0.equals(flagObj)) return false;
                        } else if (res instanceof String res0) {
                            if (res0.equals(flagObj)) return false;
                        } else if (res instanceof Character res0) {
                            if (res0.equals(flagObj)) return false;
                        } else return false;
                    } else {
                        if (first) {
                            flagObj = val;
                            first = false;
                            continue;
                        }
                        if (val instanceof Number val0) {
                            if (flagObj instanceof Number flagObj0
                                    && Double.valueOf(val0.doubleValue()).equals((flagObj0).doubleValue()))
                                return false;
                        } else if (val instanceof Boolean val0) {
                            if (val0.equals(flagObj)) return false;
                        } else if (val instanceof String val0) {
                            if (val0.equals(flagObj)) return false;
                        } else if (val instanceof Character val0) {
                            if (val0.equals(flagObj)) return false;
                        } else return false;
                    }
                }
            }
        }
        return true;
    }
    public static boolean ifLoad(JSONObject o) {
        return o == null || (load(o) instanceof Boolean r0 && r0);
    }
    public static boolean ifLoad(JSONArray a) {
        if (a == null || a.size() == 0) return true;
        for (Object i : a) {
            if (i instanceof Boolean i0)
                if (!i0) return false;
            if (i instanceof JSONObject i0)
                if (!ifLoad(i0)) return false;
            return false;
        }
        return true;
    }
    public static Object varLoad(String name) {
        return vars.get(name);
    }
}